<template>
  <a-layout-content>
    <back-bar-header text="账号中心"></back-bar-header>
    <a-layout
      class="message-container"
      :style="{ height: `${clientHeight - 188}px` }"
    >
      <a-layout-sider class="sider-menu">
        <a-menu v-model="noticeType" style="width: 200px;" mode="vertical">
          <a-menu-item :key="0"
            ><router-link to="/user/infos">个人信息</router-link></a-menu-item
          >
          <a-menu-item :key="1"
            ><router-link to="/user/security-settings">账户安全</router-link>
          </a-menu-item>
          <a-menu-item :key="2">
            <router-link to="/user/messages-settings"
              >系统/消息设置
            </router-link></a-menu-item
          >
        </a-menu>
      </a-layout-sider>
      <a-layout-content
        class="self-info-content"
        style="background: #fff; margin-right: 0;"
      >
        <a-alert
          class="self-info-alert"
          type="info"
          message="为了方便您更好的使用平台，请先补全您的信息"
          banner
          closable
        ></a-alert>
        <span class="self-info">个人信息</span>
        <a-divider></a-divider>
        <a-form
          :form="form"
          style="margin: 0 28px;"
          :wrapper-col="{ span: 12 }"
          @submit="handleSubmit"
        >
          <a-form-item>
            <span>昵称</span>
            <a-input
              v-decorator="['nickName']"
              placeholder="请输入您的昵称"
              class="input"
            >
            </a-input>
          </a-form-item>
          <a-form-item>
            <span>姓名</span>
            <a-input
              v-decorator="['realName']"
              placeholder="请输入您的姓名！"
              class="input"
            >
            </a-input>
          </a-form-item>
          <a-form-item>
            <span>职业</span>
            <a-select v-decorator="['profession']">
              <a-select-option
                v-for="profession in professionData"
                :key="profession"
              >
                {{ profession }}
              </a-select-option>
            </a-select>
          </a-form-item>
          <a-form-item>
            <span>邮箱</span>
            <a-input
              v-decorator="['email', { rules: [{ validator: validateEmail }] }]"
              placeholder="请输入您的邮箱"
              class="input"
            >
            </a-input>
          </a-form-item>
          <a-form-item>
            <span>工作单位</span>
            <a-input
              v-decorator="['workOrg']"
              type="workOrg"
              placeholder="请输入您的工作单位"
              class="input"
            >
            </a-input>
          </a-form-item>
          <a-form-item>
            <div>头像</div>
            <a-avatar
              :size="60"
              style="margin: 0 8px;"
              :src="
                avatarSrc === ''
                  ? require('@/assets/user/avatar0.png')
                  : avatarSrc
              "
            ></a-avatar>
            <a-button @click="changeAvatarModal">更换头像</a-button>
            <a-modal
              width="644px"
              :body-style="{ 'min-height': '520px' }"
              title="更换头像"
              ok-text="确定"
              cancel-text="取消"
              :visible="avatarModalVisible"
              @cancel="cancalAvatarModal"
              @ok="clickChangeAvatar"
            >
              <div style="display: flex; min-height: 460px;">
                <div class="modal-left-view">
                  <div style="align-items: center; display: flex;">
                    <div class="prefix-blue-block"></div>
                    <div class="modal-content-text">选择推荐头像</div>
                  </div>
                  <div style="margin: 20px 0;">
                    <template v-for="avatarIter in [0, 1, 2, 3]">
                      <a-avatar
                        :key="avatarIter"
                        shape="square"
                        :size="60"
                        style="margin-right: 24px;"
                        :src="require(`@/assets/user/avatar${avatarIter}.png`)"
                        :class="
                          selectedAvatar === avatarIter
                            ? 'selected-avatar'
                            : 'unselected-avatar'
                        "
                        @click="() => selectAvatar(avatarIter)"
                      ></a-avatar>
                    </template>
                  </div>
                  <div style="align-items: center; display: flex;">
                    <div class="prefix-blue-block"></div>
                    <div class="modal-content-text">本地上传</div>
                  </div>
                  <div
                    v-if="option.img !== ''"
                    style="height: 100%; margin: 20px 0 0; width: 100%;"
                    :class="
                      selectedAvatar === 1000
                        ? 'selected-avatar'
                        : 'unselected-avatar'
                    "
                    @click="selectUploadAvatar"
                  >
                    <vue-cropper
                      ref="cropper"
                      :img="option.img"
                      :output-size="option.size"
                      :output-type="option.outputType"
                      :info="true"
                      :full="option.full"
                      :can-move="option.canMove"
                      :can-move-box="option.canMoveBox"
                      :fixed-box="option.fixedBox"
                      :fixed="option.fixed"
                      :original="option.original"
                      :auto-crop="option.autoCrop"
                      :auto-crop-width="option.autoCropWidth"
                      :auto-crop-height="option.autoCropHeight"
                      :center-box="option.centerBox"
                      :high="option.high"
                      :info-true="option.infoTrue"
                      :enlarge="option.enlarge"
                      @realTime="realTime"
                      @imgLoad="imgLoad"
                    ></vue-cropper>
                  </div>
                  <a-upload
                    name="avatar"
                    class="avatar-uploader"
                    :show-upload-list="false"
                    :before-upload="beforeUpload"
                    :custom-request="customRequest"
                  >
                    <a-icon v-if="loading" type="loading" />
                    <a-button :disabled="loading">
                      <div class="ant-upload-text">
                        {{ option.img !== '' ? '重新上传' : '本地上传' }}
                      </div>
                    </a-button>
                  </a-upload>
                  <div class="modal-subtext">
                    支持JPG、PNG等格式，图片需小于2M
                  </div>
                </div>
                <a-divider type="vertical"></a-divider>
                <div class="modal-right-view">
                  <div class="modal-avatar-title">头像预览</div>
                  <div v-if="selectedAvatar === 1000" :style="previews.style">
                    <div :style="previews.div">
                      <a-avatar
                        shape="square"
                        :size="100"
                        :src="previews.url"
                        :style="previews.img"
                      ></a-avatar>
                    </div>
                  </div>
                  <div v-else>
                    <a-avatar
                      shape="square"
                      :size="100"
                      :src="imageUrl"
                    ></a-avatar>
                  </div>
                  <div class="modal-foot-subtext">
                    <div class="modal-subtext">预览</div>
                    <div class="modal-subtext">100*100</div>
                  </div>
                </div>
              </div>
            </a-modal>
          </a-form-item>
          <a-form-item>
            <a-button type="primary" html-type="submit" class="submit-button"
              >更新信息</a-button
            >
          </a-form-item>
        </a-form>
      </a-layout-content>
    </a-layout>
  </a-layout-content>
</template>

<script lang="ts">
import { Component, Vue, Watch } from 'vue-property-decorator'
import { updateUserInfo } from '@/api/user'
import UserStore from '@/store/modules/user'
import { VueCropper } from 'vue-cropper'
import BackBarHeader from '@/components/home/BackBarHeader.vue'

@Component({
  components: {
    VueCropper,
    BackBarHeader,
  },
})
export default class PersonalInformationView extends Vue {
  private form: any
  private noticeType: Array<number> = [0]
  private clientHeight = document.body.clientHeight
  private avatarModalVisible: boolean = false
  private loading: boolean = false
  private imageUrl: any = require('@/assets/user/avatar0.png')
  private previews: any = {}
  // 选中的头像 1. -1 表示未选中 2. 0、1、2、3表示选中推荐头像 3. 1000表示选中本地上传的头像
  private selectedAvatar: number = -1
  private avatarSrc: string = ''
  private isChangedAvatar: boolean = false

  private currentPage: number = 1
  private pageSize: number = 10
  private option: any = {
    img: '',
    size: 1,
    full: false,
    outputType: 'png',
    canMove: false,
    fixedBox: false,
    original: false,
    canMoveBox: true,
    autoCrop: true,
    fixed: true, // 是否开启截图框宽高固定比例
    // 只有自动截图开启 宽度高度才生效
    centerBox: false,
    high: false,
    cropData: {},
    enlarge: 1,
    mode: 'contain',
  }

  private professionData = [
    '学生',
    '互联网/IT技术',
    '高校/研究所',
    '事业单位/机关',
    '其他',
  ]

  get id() {
    return UserStore.currentUser?.id
  }

  beforeCreate() {
    this.form = this.$form.createForm(this, { name: 'login_form' })
  }

  created() {
    if (UserStore.currentUser?.id) {
      this.getUserInfo(UserStore.currentUser?.id)
    }
  }

  mounted() {
    window.addEventListener('resize', () => {
      this.clientHeight = document.body.clientHeight
    })
  }
  // 邮箱号格式rule
  public validateEmail(rule: any, value: any, callback: any) {
    if (value && !/(\S)+@(\S)+\.(\w)+/.test(value)) {
      callback('邮箱号格式错误!')
    } else {
      callback()
    }
  }

  //   // 更新个人信息
  public handleSubmit(event: any) {
    event.preventDefault()
    this.form.validateFields(async (error: Error, values: any) => {
      if (!error) {
        const passData: any = {
          params: {
            id: this.id,
            email: values.email,
            nickName: values.nickName,
            realName: values.realName,
            profession: values.profession,
            workOrg: values.workOrg,
          },
        }
        // 改变了头像的话加上头像的文件
        if (this.isChangedAvatar) {
          const formData = new FormData()
          // 本地上传的头像
          if (this.selectedAvatar === 1000) {
            let file = this.dataURLtoFile(this.avatarSrc, 'avatar.png')
            file = this.compressImg(file, 'avatar.png')
            formData.append('picture', file, file.name)
          } else if (this.selectedAvatar in [0, 1, 2, 3]) {
            // 推荐头像
            const dataUrl = this.getBase64Image(this.avatarSrc)
            let file = this.dataURLtoFile(dataUrl, 'avatar.png')
            file = this.compressImg(file, 'avatar.png')
            formData.append('picture', file, file.name)
          }
          passData.data = formData
        }
        const result = await updateUserInfo(passData)
        if (result.data.code === 100) {
          this.$message.success('更新个人信息成功！')
        }
        await this.getUserInfo(this.id)
      } else {
        console.log('error:', error)
      }
    })
  }

  // 实时更新预览
  public realTime(data: any) {
    this.previews = data
    this.previews.style = {
      width: `${this.previews.w}px`,
      height: `${this.previews.h}px`,
      overflow: 'hidden',
      margin: '0',
      zoom: 100 / this.previews.w,
    }
  }

  // 打开更新头像对话框
  public changeAvatarModal() {
    this.avatarModalVisible = true
    // 默认是未选中 打开对话框 选中第0个
    if (this.selectedAvatar === -1) {
      this.selectedAvatar = 0
    }
  }

  // 确定更改的头像
  public clickChangeAvatar() {
    if (this.selectedAvatar === 1000) {
      // 使用本地上传的头像
      const cropper = this.$refs.cropper as any
      cropper.getCropData((data: any) => {
        this.avatarSrc = data
      })
    } else if (this.selectedAvatar in [0, 1, 2, 3]) {
      this.avatarSrc = this.imageUrl
    }
    this.avatarModalVisible = false
    this.isChangedAvatar = true
  }

  // 关闭更新头像对话框
  public cancalAvatarModal() {
    this.avatarModalVisible = false
  }

  // 选择头像 require 在eslint不支持动态字符串 先暴力一下
  public selectAvatar(i: any) {
    this.selectedAvatar = i
    switch (i) {
      case 0:
        this.imageUrl = require('@/assets/user/avatar0.png')
        break
      case 1:
        this.imageUrl = require('@/assets/user/avatar1.png')
        break
      case 2:
        this.imageUrl = require('@/assets/user/avatar2.png')
        break
      case 3:
        this.imageUrl = require('@/assets/user/avatar3.png')
        break
      default:
        this.imageUrl = require('@/assets/user/avatar0.png')
    }
  }

  // 上传图片 选中
  public imgLoad() {
    this.selectedAvatar = 1000
  }

  // 点击本地上传的图片 选中
  public selectUploadAvatar() {
    this.selectedAvatar = 1000
  }

  // 上传预处理
  public beforeUpload(file: any) {
    const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png'
    if (!isJpgOrPng) {
      this.$message.error('请上传JPG/PNG格式的文件!')
    }
    const isLt2M = file.size / 1024 / 1024 < 2
    if (!isLt2M) {
      this.$message.error('图片的大小不能超过2MB!')
    }
    return isJpgOrPng && isLt2M
  }

  // 上传图片
  public customRequest(options: any) {
    const { file } = options
    this.option.img = window.URL.createObjectURL(file)
    this.loading = false
  }

  // 获取个人信息
  public async getUserInfo(id: any) {
    await UserStore.queryUserInfoById({ data: { id } })
    this.form.setFieldsValue({
      email: UserStore.currentUser?.email,
      nickName: UserStore.currentUser?.nickName,
      realName: UserStore.currentUser?.realName,
      profession: UserStore.currentUser?.profession,
      workOrg: UserStore.currentUser?.workOrg,
    })
    if (UserStore.currentUser?.picEncode) {
      this.avatarSrc = UserStore.currentUser.picEncode
    }
  }

  @Watch('id')
  queryInfoById(newValue: any) {
    this.getUserInfo(newValue)
  }

  /**
   * DataUrl转为File
   * @param {String} dataUrl - dataUrl地址
   * @param {String} fileName - file文件名
   */
  public dataURLtoFile(dataUrl: any, fileName: any) {
    const dataArray = dataUrl.split(',')
    const mime = dataArray[0].match(/:(.*?);/)[1]
    const bstr = atob(dataArray[1])
    const { length } = bstr
    const u8array = new Uint8Array(length)
    for (let i = length; i >= 0; i -= 1) {
      u8array[i] = bstr.charCodeAt(i)
    }
    return new File([u8array], fileName, { type: mime })
  }

  // image转换位base64编码
  public getBase64Image(imgUrl: any) {
    const img = new Image()
    img.src = imgUrl
    const canvas = document.createElement('canvas')
    canvas.width = img.width
    canvas.height = img.height
    const context = canvas.getContext('2d')
    context?.drawImage(img, 0, 0, img.width, img.height)
    const extension = img.src.slice(img.src.lastIndexOf('.') + 1).toLowerCase()
    const dataURL = canvas.toDataURL(`image/${extension}`)
    return dataURL
  }

  // 图片压缩函数
  public compressImg(file: any, fileName: any) {
    // 缩放图片需要的canvas（也可以在DOM中直接定义canvas标签，这样就能把压缩完的图片不转base64也能直接显示出来）
    const canvas = document.createElement('canvas')
    const context = canvas.getContext('2d')
    const img = new Image()
    img.src = this.avatarSrc

    // 图片原始尺寸
    const originWidth = img.width
    const originHeight = img.height

    // 最大尺寸限制，可通过设置宽高来实现图片压缩程度
    const maxWidth = 120
    const maxHeight = 120
    // 目标尺寸
    let targetWidth = originWidth
    let targetHeight = originHeight
    // 图片尺寸超过300x300的限制
    if (originWidth > maxWidth || originHeight > maxHeight) {
      if (originWidth / originHeight > maxWidth / maxHeight) {
        // 更宽，按照宽度限定尺寸
        targetWidth = maxWidth
        targetHeight = Math.round(maxWidth * (originHeight / originWidth))
      } else {
        targetHeight = maxHeight
        targetWidth = Math.round(maxHeight * (originWidth / originHeight))
      }
    }
    // canvas对图片进行缩放
    canvas.width = targetWidth
    canvas.height = targetHeight
    // 清除画布
    context?.clearRect(0, 0, targetWidth, targetHeight)
    // 图片压缩
    context?.drawImage(img, 0, 0, targetWidth, targetHeight)
    /* 第一个参数是创建的img对象；第二三个参数是左上角坐标，后面两个是画布区域宽高 */

    // 压缩后的图片转base64 url
    /* canvas.toDataURL(mimeType, qualityArgument),mimeType 默认值是'image/png';
    qualityArgument表示导出的图片质量，只有导出为jpeg和webp格式的时候此参数才有效，默认值是0.92 */

    const newUrl = canvas.toDataURL('image/jpeg', 0.92) // base64 格式
    return this.dataURLtoFile(newUrl, fileName)
  }
}
</script>

<style lang="less" scoped>
@import '@/constants';

.ant-layout-content {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  margin: 13px 16px 16px;
}

.sider-menu {
  height: 100px;
  margin-top: 12px;
}

li {
  text-align: center;
}

.ant-menu-vertical > .ant-menu-item {
  color: #909198;
  font-size: 16px;
  font-weight: 400;
  height: 50px;
  letter-spacing: 1px;
  line-height: 50px;
  margin: 0;
  width: 200px;
}

.ant-menu-vertical .ant-menu-item:not(:last-child) {
  border-bottom: 1px solid #e9e9e9;
  margin: 0;
}

.ant-menu:not(.ant-menu-horizontal) .ant-menu-item-selected {
  background: #fff;
  border-left: 4px solid #6973ff;
  color: #373b52;
  font-size: 16px;
  font-weight: 500;
  height: 50px;
  letter-spacing: 1px;
  line-height: 50px;
  padding-left: 12px;
  width: 200px;
}

.ant-menu-item,
.ant-menu-submenu-title {
  transition: none;
}

.ant-divider-horizontal {
  margin: 0;
}

.ant-divider-vertical {
  margin-right: 5%;
}

.self-info {
  color: #5d637e;
  font-size: 16px;
  font-weight: 500;
  height: 52px;
  letter-spacing: 1px;
  line-height: 52px;
  margin-left: 24px;
  padding-right: 12px;
}

.self-info-alert {
  align-items: center;
  background: #eaeafd;
  display: flex;
  justify-content: center;
}

.prefix-blue-block {
  background: #6973ff;
  height: 20px;
  margin-right: 11px;
  opacity: 0.6;
  width: 4px;
}

/deep/ .ant-alert-icon {
  margin-right: 5px;
  position: initial;
}

.ant-modal-title {
  letter-spacing: 1px;
}

.modal-left-view {
  display: flex;
  flex-direction: column;
  width: 60%;
}

.modal-right-view {
  width: 35%;
}

.modal-subtext {
  color: #222432;
  font-size: 12px;
  letter-spacing: 1.12px;
  opacity: 0.5;
}

.modal-avatar-title {
  color: #373b52;
  font-size: 16px;
  letter-spacing: 1px;
}

.modal-foot-subtext {
  display: flex;
  justify-content: space-between;
  width: 100px;
}

.ant-form-item {
  margin-bottom: 16px;
}

.avatar-uploader {
  margin: 20px 5px 10px 0;
}

.avatar-preview {
  height: 300px;
  margin: 20px 0 0;
  width: 300px;
}

.selected-avatar {
  border: 3px solid #6973ff;
}

.unselected-avatar {
  padding: 3px;
}
</style>
